﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ReAnimation.Infrastructure.Services.Interfaces;
using ReAnimation.Domain;
using OpenBabel;
using ReAnimation.Domain.Policies.Interfaces;
using ReAnimation.Helpers.Common;
using Sharp3D.Math.Core;
using System.Diagnostics;

namespace ReAnimation.Infrastructure.Services
{
    public class ZMatrixService: IZMatrixService
    {
        private IZMatrixPolicy _zMatrixPolicy;
        private IOpenBabelService _openBabelService;
        //TODO: should not use Policy because it from Domain layer that is above the Infrastructure layer
        public ZMatrixService(IZMatrixPolicy zMatrixPolicy,IOpenBabelService openBabelService)
        {
            _zMatrixPolicy = zMatrixPolicy;
            _openBabelService = openBabelService;
        }

        #region IZMatrixService Members
        //TODO: refactor
        public bool ConvertZMatrixToCartesian(ZMatrix zMatrix, Molecule molecule)
        {
            if (!_zMatrixPolicy.CheckZMatrix(zMatrix)) 
                return false;

            OBMol mol = _openBabelService.ConvertZMatrixToOBMol(zMatrix);

            if (mol == null) 
                return false;

            IList<Atom> newAtoms = new List<Atom>();
            IList<Link> newLinks = new List<Link>();

            IDictionary<uint, Atom> _atoms = new Dictionary<uint,Atom>();

            int index = 0;
            foreach (var atom in mol.Atoms())
            {
                CDoubleArray positionArray = atom.GetCoordinate();

                Atom sceneAtom = new Atom()
                {
                    AtomDescription = zMatrix.ZMatrixLines[index].AtomDescription,
                    Position = new Vector3F((float)positionArray.getitem(0),
                                            (float)positionArray.getitem(1),
                                            (float)positionArray.getitem(2))
                };

                newAtoms.Add(sceneAtom);
                _atoms[atom.GetIdx()] = sceneAtom;

                index++;
            }

     
            foreach (var bond in mol.Bonds())
            {
                Link link = new Link()
                    {
                        Atom1 = _atoms[bond.GetBeginAtom().GetIdx()],
                        Atom2 = _atoms[bond.GetEndAtom().GetIdx()]
                    };
                //TODO: refactor
                if (bond.IsSingle())
                {
                    link.LinkType = MoleculeLinkType.Single;
                    newLinks.Add(link);
                    continue;
                }
                if (bond.IsDouble())
                {
                    link.LinkType = MoleculeLinkType.Double;
                    newLinks.Add(link);
                    continue;
                }
                if (bond.IsTriple())
                {
                    link.LinkType = MoleculeLinkType.Triple;
                    newLinks.Add(link);
                    continue;
                }
                if (bond.IsAromatic())
                {
                    link.LinkType = MoleculeLinkType.Sesquialteral;
                    newLinks.Add(link);
                    continue;
                }
            }

            molecule.SetAtomsAndLinks(newAtoms,newLinks);
            return true;
        }

        public ZMatrix ConvertOBMolToZMatrix(OBMol molecule)
        {
            return null;
        }

        #endregion
      
        
    }
}
